// ==UserScript==
// @name         《打工方块人》
// @namespace    https://gitee.com/yiyuzi/youhou/tree/master/
// @version      1.2
// @description  摸鱼鱼鱼
// @author       UI设计：可达；编程：一语子
// @include      *
// @require      https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js
// @match        http://*/*
// @icon         
// @grant        GM_registerMenuCommand
// @grant        GM_unregisterMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// ==/UserScript==

'use strict';
// console.log("打工方块人 start");

// 10*10的棋盘
var chessboardNum;
var chessboard;
// 棋子种类
var chessType;
// 棋子种类数量
var chessTypeNum;
// 备选棋子数量
var chessSelectNum;
// 备选棋子类型
var chessSelectType;
// 备选棋子颜色
var chessSelectColorType;
// 分数
var chessScore;
// 颜色种类
var colorType;
// 棋子大小
var chessHeight;
// 皮肤种类
var skinType;

var menu_chess_ALL = [
    ['menu_chess_height', '格子高度', 20, 'input'],
    ['menu_chess_top', '距上', 0, 'input'],
    ['menu_chess_left', '距左', 0, 'input'],
    ['menu_chess_skin', '外观', 'green', 'select', [['purple','藤萝紫'], ['green', '护眼绿'], ['blue','知乎蓝']]]
];

chessInit();

// 初始化棋盘
function chessInit(){
    for (let i = 0; i < menu_chess_ALL.length; i++){
        if (GM_getValue(menu_chess_ALL[i][0]) == null){
            GM_setValue(menu_chess_ALL[i][0], menu_chess_ALL[i][2])
        };
    }
    GM_registerMenuCommand("设置", function(){menu_chess_setting("设置", true, menu_chess_ALL)});
    chessboardNum = 10;
    chessTypeNum = chessSelectNum = chessScore = 0;
    chessboard = new Array(chessboardNum).fill('');
    chessboard = chessboard.map((ele)=>new Array(chessboardNum).fill(false));
    chessType = new Array(15).fill('');
    chessType = chessType.map((ele)=>new Array(4).fill(''));
    chessTypeInit();
    colorType = {"purple":["#00f2fe", "#a18cd1", "#ff9a9e", "#d4fc79", "#96e6a1", "#84fab0", "#8fd3f4", "#a1c4fd", "#c2e9fb", "#4facfe", "#43e97b", "#38f9d7", "#fa709a", "#fee140"],
                "green":["#00f2fe", "#a18cd1", "#ff9a9e", "#d4fc79", "#96e6a1", "#84fab0", "#8fd3f4", "#a1c4fd", "#c2e9fb", "#4facfe", "#43e97b", "#38f9d7", "#fa709a", "#fee140"],
               "blue":["#fcb73f", "#fca13f", "#fc7d3f", "#fc5e3f"]};
    if (!GM_getValue("chessScoreMax")) {GM_setValue("chessScoreMax", 0)}
    if (typeof(GM_getValue("hiddenGame")) == undefined) {GM_setValue("hiddenGame", false)}
    chessHeight = Number(GM_getValue("menu_chess_height"));
    // 0棋盘背景色、1开始背景色、2隐藏背景色、3格子阴影、4格子高亮阴影
    skinType = {"purple":["#ded7f5", "#ffc0da", "#907dde", "0px 0px 2px 2px rgba(144, 125, 222, .1)", "0px 0px 4px 4px rgba(255, 192, 218, .8)"],
                "green":["#B3E582", "#fed404", "#65cb65", "0px 0px 2px 2px rgba(105, 201, 104, .1)", "0px 0px 4px 4px rgba(254, 212, 2, .8)"],
               "blue":["#1482fd", "#1482fd", "#1482fd", "0px 0px 2px 2px rgba(22, 128, 255, .1)", "0px 0px 4px 4px rgba(33, 30, 143, .8)"]};

    setChessboardStyle();
    let _html = `<link href="https://fonts.font.im/css?family=Oswald:500" rel="stylesheet">
    <button id="hiddenGame">隐藏</button>
    <div id="chessGame">
    <div id="chessHead">
    <button id="startGame">开始</button>
    <div id="chessScoreMax">最高：${GM_getValue("chessScoreMax")}</div>
    </div>
    <div id="chessSaveAndLoad">
    <button id="chessSaveGame">存档</button>
    <div id="chessScore">当前：${chessScore}</div>
    <button id="chessLoadGame">读档</button>
    </div>
    <div id='chessboard'>`;
    for (let i = 0; i < chessboardNum; i++){
        for (let j = 0; j < chessboardNum; j++){
            _html += `<div class="chessCell" id="${"chessCell"+i+j}"></div>`;
        }
    }
    _html += `</div><div id="chessWaitSelectBoard">`
    for (let i = 0; i < 3; i++){
        _html += `<div class="chessWaitSelect" id="${"chessWaitSelect"+i}"></div>`;
    }
    _html += `</div></div>`;
    document.body.insertAdjacentHTML('beforeend', _html);
    function bindStartGameBtn(){
        document.getElementById("startGame").addEventListener("click", startGame);
    }
    function bindHiddenGameBtn(){
        document.getElementById("hiddenGame").addEventListener("click", function(){
            if(GM_getValue("hiddenGame")){
                $("#hiddenGameStyle").remove();
                GM_setValue("hiddenGame", false);
            }else {
                $("body").append("<style id='hiddenGameStyle'>#hiddenGame {background: none; color:#adbac7}#chessGame {display:none}</style>");
                GM_setValue("hiddenGame", true);
            }
        });
    }
    function bindSaveGameBtn(){
        document.getElementById("chessSaveGame").addEventListener("click", chessSave);
    }
    function bindLoadGameBtn(){
        document.getElementById("chessLoadGame").addEventListener("click", chessLoad);
    }
    setTimeout(bindStartGameBtn, 100);
    setTimeout(bindHiddenGameBtn, 100);
    setTimeout(bindSaveGameBtn, 100);
    setTimeout(bindLoadGameBtn, 100);
    setTimeout(suspensionChessboard, 100);
    if(GM_getValue("hiddenGame") && !$("#hiddenGameStyle").length>0){
        $("body").append("<style id='hiddenGameStyle'>#hiddenGame {background: none; color:#adbac7}#chessGame {display:none}</style>");
    }else if(!GM_getValue("hiddenGame") && $("#hiddenGameStyle").length>0){
        $("#hiddenGameStyle").remove();
    }
}

// 初始化样式
function setChessboardStyle(){
    $("#chessboardStyle").remove();
    let _html = `<style id="chessboardStyle">
    #hiddenGame, #startGame, #chessSaveGame, #chessLoadGame {
    padding: 0;
    color: #fff;
    cursor: pointer;
    border: none;
    outline: none;
    font-size: ${chessHeight/1.8}px;
    font-family: 'Oswald', sans-serif;
    height: ${chessHeight*1}px;
    width: ${chessHeight*2}px;
    vertical-align:middle;
    text-align: center;
    padding-bottom:  ${chessHeight/8}px;
    }
    #hiddenGame {
    z-index: 2001;
    position: fixed;
    top: ${Number(GM_getValue("menu_chess_top"))+chessHeight*1.25}px;
    left: ${Number(GM_getValue("menu_chess_left"))+chessHeight*9}px;
    background: ${skinType[GM_getValue('menu_chess_skin')][2]};
    border-radius: 3px ${chessHeight*5}px ${chessHeight*5}px 3px;
    }
    #startGame {
    background: ${skinType[GM_getValue('menu_chess_skin')][1]};
    border-radius: ${chessHeight*5}px 3px 3px ${chessHeight*5}px;
    }
    #chessLoadGame {
    background: #fff;
    color: ${skinType[GM_getValue('menu_chess_skin')][1]};
    border-radius: 3px ${chessHeight*5}px ${chessHeight*5}px 3px;
    }
    #chessSaveGame {
    background: #fff;
    color: ${skinType[GM_getValue('menu_chess_skin')][2]};
    border-radius: ${chessHeight*5}px 3px 3px ${chessHeight*5}px;
    }
    #chessGame {
    text-align: left;
    z-index: 2000;
    position: fixed;
    top: ${GM_getValue("menu_chess_top")}px;
    left: ${GM_getValue("menu_chess_left")}px;
    background: ${skinType[GM_getValue('menu_chess_skin')][0]};
    padding: ${chessHeight}px;
    border-radius: ${chessHeight}px;
    }
    #chessGame div{
    color: #fff;
    font-size: ${chessHeight/1.5}px;
    font-family: 'Oswald', sans-serif;
    }
    #chessHead, #chessSaveAndLoad{
    text-align: center;
    display: grid;
    /* 划分行列 */
    grid-template-rows: repeat(1,${chessHeight*1.5}px);
    grid-template-columns: ${chessHeight*2}px ${chessHeight*6}px ${chessHeight*2}px;
    align-items: center;
    justify-items: center;
    /* justify-content属性是整个内容区域在容器里面的水平位置（左中右），align-content属性是整个内容区域的垂直位置（上中下）。 */
    justify-content: center;
    align-content: center;
    }
    #chessboard {
    display: grid;
    /* 划分行列 */
    grid-template-rows: repeat(10, ${chessHeight}px);
    grid-template-columns: repeat(10, ${chessHeight}px);
    align-items: center;
    justify-items: center;
    justify-content: center;
    align-content: center;
    margin-bottom: 5px;
	}
    .chessCell {
    background: #fff;
    box-shadow: ${skinType[GM_getValue('menu_chess_skin')][3]};
    height: ${chessHeight-5}px;
    width: ${chessHeight-5}px;
    transition: background-color 500ms;
    border-radius: ${chessHeight/6}px;
    }
    #chessWaitSelectBoard {
    display: grid;
    grid-template-rows: repeat(1, ${chessHeight*10/3}px);
    grid-template-columns: repeat(3, ${chessHeight*10/3}px);
    align-items: center;
    justify-items: center;
    justify-content: center;
    align-content: center;
    }
    .chessWaitSelect {
    background: #fff;
    box-shadow: ${skinType[GM_getValue('menu_chess_skin')][3]};
    height: ${chessHeight*10/3-5}px;
    width: 90%;
    display: flex;
    justify-content: center;
    align-items: center;
    border-radius: ${chessHeight/3}px;
    }
    #chessScore {
    height: auto;
    width: auto;
    }
    </style>`
    document.body.insertAdjacentHTML('beforeend', _html);
}

// 初始化棋子类型
function chessTypeInit() {
	chessType[chessTypeNum++][0] = [[true]];
    chessType[chessTypeNum++][0] = [[true, true]];
    chessType[chessTypeNum++][0] = [[true, true, true]];
    chessType[chessTypeNum++][0] = [[true, true, true, true]];
    chessType[chessTypeNum++][0] = [[true, true, true, true, true]];
    chessType[chessTypeNum++][0] = [[true, true],
                                    [true, true]];
    chessType[chessTypeNum++][0] = [[true, true],
                                    [true, false]];
    chessType[chessTypeNum++][0] = [[false, true, true],
                                    [true, true, false]];
    chessType[chessTypeNum++][0] = [[true, true, false],
                                    [false, true, true]];
    chessType[chessTypeNum++][0] = [[true, true, true],
                                    [true, false, false]];
    chessType[chessTypeNum++][0] = [[true, true, true],
                                    [false, false, true]];
    chessType[chessTypeNum++][0] = [[true, true, true],
                                    [false, true, false]];
    chessType[chessTypeNum++][0] = [[true, true, true],
                                    [true, false, true],
                                    [true, false, true]];

    // chessTypeNum种形状
	for (let shape = 0; shape < chessTypeNum; shape++) {
        // 顺时针旋转
		for (let form = 0; form < 3; form++) {
            let row = chessType[shape][form].length;
            let col = chessType[shape][form][0].length;
            chessType[shape][form + 1] = new Array(col).fill('');
            chessType[shape][form + 1] = chessType[shape][form + 1].map((ele)=>new Array(row));
			for (let i = 0; i < row; i++) {
				for (let j = 0; j < col; j++) {
					chessType[shape][form + 1][col - 1 - j][i] = chessType[shape][form][i][j];
				}
			}
		}
	}
}

// 返回min到max-1中任意整数
function getRndInteger(min, max) {
    return Math.floor(Math.random() * (max - min) ) + min;
}

function createChess(){
    chessSelectType = [];
    chessSelectColorType = [];
    for (let k = chessSelectNum; k < 3; k++){
        let chess = chessType[getRndInteger(0, chessTypeNum-(chessScore < 200 ? 1 : 0))][getRndInteger(0, 4)];
        let row = chess.length;
        let col = chess[0].length;
        chessSelectType.push(chess);
        chessSelectColorType.push(colorType[GM_getValue('menu_chess_skin')][getRndInteger(0, colorType[GM_getValue('menu_chess_skin')].length-1)]);
        let _html = `<div id="${"chessFall"+k}">`;
        for(let i = 0; i < row; i++){
            for(let j = 0; j < col; j++){
                _html += `<div id="${"chessSelect"+k+i+j}" class="chessSelect" style="${chess[i][j] ? "background: "+chessSelectColorType[k] : "opacity: 0%"};"></div>`;
            }
        }
        _html += `<style id="${"chessFallStyle"+k}">
        #${"chessFall"+k} {
        cursor:pointer;
        display: grid;
        grid-template-rows: repeat(${row}, ${chessHeight/2}px);
        grid-template-columns: repeat(${col},${chessHeight/2}px);
        }
        #${"chessFall"+k} .chessSelect{
        border-radius: ${chessHeight/10}px;height: ${chessHeight/2.2}px; width: ${chessHeight/2.2}px;
        }
        </style></div>`;
        document.getElementById("chessWaitSelect"+k).insertAdjacentHTML('beforeend', _html);
        suspensionChess("chessFall"+k);
    }
    chessSelectNum = 3;
    // 检查是否还能放置棋子
    setTimeout(isCanSetChess, 1000);
}

// 移动棋子
function suspensionChess(dragId) {
    var startEvt, moveEvt, endEvt;
    // 判断是否支持触摸事件
    if ('ontouchstart' in window) {
        startEvt = 'touchstart';
        moveEvt = 'touchmove';
        endEvt = 'touchend';
    } else {
        startEvt = 'mousedown';
        moveEvt = 'mousemove';
        endEvt = 'mouseup';
    }
    // 获取元素
    var drag = document.getElementById(dragId);
    // 标记是拖曳还是点击
    var isClick = true;
    // 标记位置
    var disX, disY, left, top, starX, starY;
    // 拖动的棋子
    var k = dragId.charAt(dragId.length - 1);
    var chess = chessSelectType[k];
    var row = chess.length;
    var col = chess[0].length;
    // 当前棋盘左上角位置
    var chessGameEle = document.getElementById("chessGame");
    var chessboardEle = document.getElementById("chessboard");
    var chessboardX;
    var chessboardY;
    var chessScoreLevel = [0, 10, 40, 80, 160, 320, 640, 1280, 2560, 5120, 10240];

    drag.addEventListener(startEvt, startFun);

    function startFun(e) {
        // 创建临时样式
        let _html = `<style id='tempStyle'>
        #${dragId} {
        position: fixed;
        grid-template-rows: repeat(${row},${chessHeight}px);
        grid-template-columns: repeat(${col},${chessHeight}px);
        }
        #${dragId} .chessSelect{
        border-radius: ${chessHeight/6}px;
        height: ${chessHeight-5}px;
        width: ${chessHeight-5}px;
        }
        </style>`;
        document.body.insertAdjacentHTML('beforeend', _html);
        // 阻止页面的滚动，缩放
        e.preventDefault();
        // 兼容IE浏览器
        e = e || window.event;
        isClick = true;
        // 按下时的坐标
        starX = e.touches ? e.touches[0].clientX : e.clientX;
        starY = e.touches ? e.touches[0].clientY : e.clientY;
        // 相对于拖动元素左上角的位置
        disX = starX - drag.offsetLeft;
        disY = starY - drag.offsetTop;
        // 记录原先的位置
        starX = drag.offsetLeft;
        starY = drag.offsetTop;
        // 按下之后监听后续事件
        document.addEventListener(moveEvt, moveFun);
        document.addEventListener(endEvt, endFun);
        chessboardX = chessGameEle.offsetLeft + chessboardEle.offsetLeft;
        chessboardY = chessGameEle.offsetTop + chessboardEle.offsetTop;
    }

    function moveFun(e) {
        // 兼容IE浏览器
        e = e || window.event;
        isClick = false;
        left = (e.touches ? e.touches[0].clientX : e.clientX) - disX;
        top = (e.touches ? e.touches[0].clientY : e.clientY) - disY;
        // 限制拖拽的X范围，不能拖出屏幕
        if (left < 0) {
            left = 0;
        } else if (left > document.documentElement.clientWidth - drag.offsetWidth) {
            left = document.documentElement.clientWidth - drag.offsetWidth;
        }
        // 限制拖拽的Y范围，不能拖出屏幕
        if (top < 0) {
            top = 0;
        } else if (top > document.documentElement.clientHeight - drag.offsetHeight) {
            top = document.documentElement.clientHeight - drag.offsetHeight;
        }
        // 触发对应棋盘格子样式变化;
        for (let i = 0; i < chessboardNum; i++){
            for (let j = 0; j < chessboardNum; j++){
                $("#chessCell"+i+j).css("box-shadow", skinType[GM_getValue('menu_chess_skin')][3]);
            }
        }
        let y = Math.round((drag.offsetLeft-chessboardX)/chessHeight);
        let x = Math.round((drag.offsetTop-chessboardY)/chessHeight);
        if (x >= 0 && y >= 0 && x+row <= chessboardNum && y+col <= chessboardNum){
            let chessColorTemp = [];
            let isColor = true;
            for(let i = x; i < x+row && isColor; i++){
                for(let j = y; j < y+col && isColor; j++){
                    if(chess[i-x][j-y]){
                        if(chessboard[i][j]){
                            isColor = false;
                            break;
                        }
                        chessColorTemp.push([i, j]);
                    }
                }
            }
            if (isColor){
                for(let i = 0; i < chessColorTemp.length; i++){
                    $("#chessCell"+chessColorTemp[i][0]+chessColorTemp[i][1]).css("box-shadow", skinType[GM_getValue('menu_chess_skin')][4]);
                }
            }
        }
        drag.style.left = left + 'px';
        drag.style.top = top + 'px';
    }

    function endFun(e) {
        document.removeEventListener(moveEvt, moveFun);
        document.removeEventListener(endEvt, endFun);
        // 恢复样式，将方块放置到棋盘上或移回原位
        for (let i = 0; i < chessboardNum; i++){
            for (let j = 0; j < chessboardNum; j++){
                $("#chessCell"+i+j).css("box-shadow", skinType[GM_getValue('menu_chess_skin')][3]);
            }
        }
        let y = Math.round((drag.offsetLeft-chessboardX)/chessHeight);
        let x = Math.round((drag.offsetTop-chessboardY)/chessHeight);
        $("#tempStyle").remove();
        if (x >= 0 && y >= 0 && x+row <= chessboardNum && y+col <= chessboardNum){
            let chessColorTemp = [];
            let isColor = true;
            for(let i = x; i < x+row && isColor; i++){
                for(let j = y; j < y+col && isColor; j++){
                    if(chess[i-x][j-y]){
                        if(chessboard[i][j]){
                            isColor = false;
                            break;
                        }
                        chessColorTemp.push([i, j]);
                    }
                }
            }
            if (isColor){
                for(let i = 0; i < chessColorTemp.length; i++){
                    let tx = chessColorTemp[i][0];
                    let ty = chessColorTemp[i][1];
                    chessboard[tx][ty] = true;
                    $("#chessCell"+tx+ty).css("background", chessSelectColorType[k]);
                }
                // 检查这几行有没有能消除的，更新分数
                // 深拷贝棋盘，避免十字消除只能消某一行的bug
                let chessboardTemp = JSON.parse(JSON.stringify(chessboard))
                let level = 0;
                for(let i = x; i < x+row; i++){
                    let isClear = true;
                    for(let j = 0; j < chessboardNum; j++){
                        isClear = isClear && chessboardTemp[i][j];
                    }
                    if(isClear) {
                        level++;
                        for(let j = 0; j < chessboardNum; j++){
                            $("#chessCell"+i+j).css("background", "#fff");
                            chessboard[i][j] = false;
                        }
                    }
                }
                for(let j = y; j < y+col; j++){
                    let isClear = true;
                    for(let i = 0; i < chessboardNum; i++){
                        isClear = isClear && chessboardTemp[i][j];
                    }
                    if(isClear) {
                        level++;
                        for(let i = 0; i < chessboardNum; i++){
                            $("#chessCell"+i+j).css("background", "#fff");
                            chessboard[i][j] = false;
                        }
                    }
                }
                chessScore += chessScoreLevel[level];
                $("#chessScore").text("当前："+chessScore);
                if (chessScore > GM_getValue("chessScoreMax")){
                    GM_setValue("chessScoreMax", chessScore);
                    $("#chessScoreMax").text("最高："+chessScore);
                }
                $("#"+dragId).remove();
                chessSelectType[k] = null;
                chessSelectNum--;
                if(chessSelectNum == 0){
                    createChess();
                }else {
                    // 检查是否还能放置棋子
                    setTimeout(isCanSetChess, 500);
                }
                return;
            }
        }
        drag.style.left = starX + 'px';
        drag.style.top = starY + 'px';
    }
}

// 移动棋盘
function suspensionChessboard() {
    var startEvt, moveEvt, endEvt;
    if ('ontouchstart' in window) {
        startEvt = 'touchstart';
        moveEvt = 'touchmove';
        endEvt = 'touchend';
    } else {
        startEvt = 'mousedown';
        moveEvt = 'mousemove';
        endEvt = 'mouseup';
    }
    var chessGameElm = document.getElementById("chessGame");
    var hiddenBtnElm = document.getElementById("hiddenGame");
    var disX, disY, left, top, starX, starY;

    chessStopPropagation("#chessHead");
    chessStopPropagation("#chessSaveAndLoad");
    chessStopPropagation("#chessboard");
    chessStopPropagation("#chessWaitSelectBoard");

    chessGameElm.addEventListener(startEvt, function (e) {
        // 阻止页面的滚动，缩放
        e.preventDefault();
        // 兼容IE浏览器
        e = e || window.event;
        // 按下时的坐标
        starX = e.touches ? e.touches[0].clientX : e.clientX;
        starY = e.touches ? e.touches[0].clientY : e.clientY;
        // 相对于拖动元素左上角的位置
        disX = starX - chessGameElm.offsetLeft;
        disY = starY - chessGameElm.offsetTop;
        // 按下之后才监听后续事件
        document.addEventListener(moveEvt, moveFun);
        document.addEventListener(endEvt, endFun);
    })

    function moveFun(e) {
        // 兼容IE浏览器
        e = e || window.event;
        left = (e.touches ? e.touches[0].clientX : e.clientX) - disX;
        top = (e.touches ? e.touches[0].clientY : e.clientY) - disY;
        // 限制拖拽的X范围，不能拖出屏幕
        if (left < 0) {
            left = 0;
        } else if (left > document.documentElement.clientWidth - chessGameElm.offsetWidth) {
            left = document.documentElement.clientWidth - chessGameElm.offsetWidth;
        }
        // 限制拖拽的Y范围，不能拖出屏幕
        if (top < 0) {
            top = 0;
        } else if (top > document.documentElement.clientHeight - chessGameElm.offsetHeight) {
            top = document.documentElement.clientHeight - chessGameElm.offsetHeight;
        }
        chessGameElm.style.left = left + 'px';
        chessGameElm.style.top = top + 'px';
        hiddenBtnElm.style.left = (left + chessHeight*9) + 'px';
        hiddenBtnElm.style.top = (top + chessHeight*1.25)+ 'px';
    }

    function endFun(e) {
        document.removeEventListener(moveEvt, moveFun);
        document.removeEventListener(endEvt, endFun);
        GM_setValue("menu_chess_left", left);
        GM_setValue("menu_chess_top", top);
    }
}

function startGame(){
    chessSelectNum = chessScore = 0;
    $("#chessScore").text("当前：" + chessScore);
    $("#tempStyle").remove();
    $("#chessFall0").remove();
    $("#chessFall1").remove();
    $("#chessFall2").remove();
    for (let i = 0; i < 10; i++){
        for (let j = 0; j < 10; j++){
           chessboard[i][j] = false;
           $("#chessCell"+i+j).css("background", "#fff");
           $("#chessCell"+i+j).css("box-shadow", skinType[GM_getValue('menu_chess_skin')][3]);
        }
    }
    createChess();
}

function isCanSetChess(){
    if(chessSelectNum == 0){
        return;
    }
    let isAllClear = 3;
    for(let q = 0; q < 3; q++){
        if(chessSelectType[q] == null){
            isAllClear--;
            continue;
        }
        let row = chessSelectType[q].length;
        let col = chessSelectType[q][0].length;
        let isClear = false;
        for(let ax = 0; ax < chessboardNum-row+1 && !isClear;ax++){
            for(let ay = 0; ay < chessboardNum-col+1 && !isClear; ay++){
                isClear = true;
                for(let i = ax; i < ax+row && isClear; i++){
                    for(let j = ay; j < ay+col && isClear; j++){
                        isClear = isClear && !(chessSelectType[q][i-ax][j-ay] && chessboard[i][j]);
                    }
                }
            }
        }
        if (!isClear) {
            isAllClear--;
        }
    }
    if(isAllClear == 0) {
        $("#tempStyle").remove();
        GM_deleteValue("chessboardRecord");
        alert("游戏结束");
    }
}

// 设置
function menu_chess_setting(title, line, menu) {
    let _br = '', _html = `<style>
        #all_light { /*整个弹窗的页面*/
            opacity: 0.8; /*透明度*/
            width: 100%; /*宽度*/
            height: 100%; /*高度，不能百分百*/
            background: #000; /*背景色*/
            position: fixed;
            top: 0;
            left: 0; /*定位*/
            display: block; /*隐藏*/
            z-index: 2001; /*覆盖*/
        }
        #contes { /* 弹框的页面*/
            z-index: 2002;
            position: fixed;
            top: 10%;
            left: 50%;
            -webkit-transform: translate(-50%, 0%);
            -moz-transform: translate(-50%, 0%);
            -ms-transform: translate(-50%, 0%);
            -o-transform: translate(-50%, 0%);
            transform: translate(-50%, 0%);
            width: auto;
            min-width: 40%;
            max-width: 90%;
            height: auto;
            max-height: 80%;
            min-height: 40%;
            color: #535353;
            background-color: #fff;
            border-radius: 3px;
            overflow-x:hidden;
            overflow-y:auto;
            font-size: 15px !important;
        }
        .ballInput{
            margin: 3px;
            outline-style: none;
            border: none;
            box-shadow: 0 0 3px #696969,0 0 3px #696969;
            padding: 2px;
        }
        .ballInput:focus{
            border-color: #66afe9;
            outline: 0;
            -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(30,144,255,.6);
            box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(30,144,255,.6)
        }
        .ballLabel{
            width: auto;
            min-width: 40%;
            display: inline-block;
            cursor: default;
        }
        #closeBtn, #defaultBtn, #submitBtn{
            margin: 10px;
            padding: 5px;
            border-radius: 5px;
            background: #4B98F0;
            color: #fff;
            cursor: pointer;
            min-width: 80px;
        }</style>
        <div id="contes">
        <div><div style="padding: 10px 0px 5px 10px; font-size:20px">${title}</div>
        <hr> <form id="ballSettingForm" style="margin: 5% 10% 5% 10%;">
        `
    if (line) _br = '<br>'
    for (let i=0; i<menu.length; i++) {
        let v = GM_getValue(menu[i][0]) ? GM_getValue(menu[i][0]) : menu[i][2];
        if (menu[i][3] == 'select'){
            _html += `<label class ="ballLabel">${menu[i][1]}</label><select id="${menu[i][0]}" name="chessSkin">`;
            for(let j = 0, len = menu[i][4].length; j < len; j++){
            _html += `<option value="${menu[i][4][j][0]}"`;
            if(menu[i][4][j][0] == GM_getValue(menu[i][0])){
                _html += ` selected`;
            }
            _html +=`>${menu[i][4][j][1]}</option>`;
            }
            _html += `</select><br/>`;
        }else if (menu[i][3] == 'checkbox' && GM_getValue(menu[i][0])){
            _html += `<label class ="ballLabel">${menu[i][1]}</label><input id="${menu[i][0]}" class="ballInput" name="${menu[i][0]}" type="${menu[i][3]}" value="${v}" checked>${_br}`
        }else {
            _html += `<label class ="ballLabel">${menu[i][1]}</label><input id="${menu[i][0]}" class="ballInput" name="${menu[i][0]}" type="${menu[i][3]}" value="${v}">${_br}`
        }
    }
    _html += `<input id="closeBtn" type="button" value="关闭"><input id="defaultBtn" type="button" value="恢复默认值"><input id="submitBtn" type="button" value="应用"> </form> </div></div><div id="all_light"></div>${_br}`
    document.body.insertAdjacentHTML('beforeend', _html); // 插入网页末尾
    setTimeout(function() { // 延迟 100 毫秒，避免太快
        // 关闭按钮 点击事件
        $('#closeBtn').bind('click', closeSetting);
        // 点击周围空白处 = 点击关闭按钮
        $("#all_light").bind('click', closeSetting);
        $("#defaultBtn").bind('click', function(){
            for (let i=0;i<menu.length;i++){
                $("#"+menu[i][0]).val(menu[i][2]);
            };
        });
        $('#submitBtn').bind('click', function(){
            for (let i=0; i<menu.length; i++) {
                if (menu[i][3] == 'select'){
                    GM_setValue(menu[i][0], $("#"+menu[i][0]+" option:selected").val());
                }else if (menu[i][3] == 'checkbox'){
                    GM_setValue(menu[i][0], $("#"+menu[i][0]).is(":checked"));
                }else {
                    GM_setValue(menu[i][0], $("#"+menu[i][0]).val());
                }
            }
            chessHeight = Number(GM_getValue("menu_chess_height"));
            setChessboardStyle();
            if(GM_getValue("hiddenGame")){
                $("#hiddenGameStyle").remove();
                $("body").append("<style id='hiddenGameStyle'>#hiddenGame {background: none; color:#adbac7}#chessGame {display:none}</style>");
            }
        });
    }, 100);

    function closeSetting(){
        $("#all_light").remove();
        $('#contes').remove();
    }
}

function chessStopPropagation(idOrClass){
    $(idOrClass).mousedown(function(event){
        event.stopPropagation();
    });
}

// 存档
function chessSave(){
    let chessboardColor = new Array(chessboardNum).fill('');
    chessboardColor = chessboardColor.map((ele)=>new Array(chessboardNum).fill(false));
    for (let i = 0; i < chessboardNum; i++){
        for (let j = 0; j < chessboardNum; j++){
            chessboardColor[i][j] = $("#chessCell"+i+j).css("background-color");
        }
    }
    let chessboardRecord = {};
    chessboardRecord.chessboardColor = chessboardColor;
    chessboardRecord.chessboard = chessboard;
    chessboardRecord.chessScore = chessScore;
    chessboardRecord.chessSelectNum = chessSelectNum;
    chessboardRecord.chessSelectType = chessSelectType;
    chessboardRecord.chessSelectColorType = chessSelectColorType;
    GM_setValue("chessboardRecord", chessboardRecord);
}

// 读档
function chessLoad(){
    let chessboardRecord = GM_getValue("chessboardRecord");
    if (typeof(chessboardRecord) == undefined){
        return;
    }
    $("#tempStyle").remove();
    $("#chessFall0").remove();
    $("#chessFall1").remove();
    $("#chessFall2").remove();
    chessboard = chessboardRecord.chessboard;
    let chessboardColor = chessboardRecord.chessboardColor;
    for (let i = 0; i < chessboardNum; i++){
        for (let j = 0; j < chessboardNum; j++){
            $("#chessCell"+i+j).css("background", chessboardColor[i][j]);
        }
    }
    if (chessboardRecord.chessScore) {
        chessScore = chessboardRecord.chessScore;
        $("#chessScore").text("当前：" + chessScore);
    }
    if (GM_getValue("chessScoreMax")) {$("#chessScoreMax").text("最高：" + GM_getValue("chessScoreMax"));}
    if (chessboardRecord.chessSelectNum && chessboardRecord.chessSelectType && chessboardRecord.chessSelectColorType) {
        chessSelectNum = chessboardRecord.chessSelectNum;
        chessSelectType = chessboardRecord.chessSelectType;
        chessSelectColorType = chessboardRecord.chessSelectColorType;
        for (let k = 0; k < 3; k++){
            if(chessSelectType[k] == null){
                continue;
            }
            let chess = chessSelectType[k];
            let row = chess.length;
            let col = chess[0].length;
            let _html = `<div id="${"chessFall"+k}">`;
            for(let i = 0; i < row; i++){
                for(let j = 0; j < col; j++){
                    _html += `<div id="${"chessSelect"+k+i+j}" class="chessSelect" style="${chess[i][j] ? "background: "+chessSelectColorType[k] : "opacity: 0%"};"></div>`;
                }
            }
            _html += `<style id="${"chessFallStyle"+k}">
        #${"chessFall"+k} {
        cursor:pointer;
        display: grid;
        grid-template-rows: repeat(${row}, ${chessHeight/2}px);
        grid-template-columns: repeat(${col},${chessHeight/2}px);
        }
        #${"chessFall"+k} .chessSelect{
        border-radius: ${chessHeight/10}px;height: ${chessHeight/2.2}px; width: ${chessHeight/2.2}px;
        }
        </style></div>`;
            document.getElementById("chessWaitSelect"+k).insertAdjacentHTML('beforeend', _html);
            suspensionChess("chessFall"+k);
        }
        // 检查是否还能放置棋子
        setTimeout(isCanSetChess, 1000);
    }
}